﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using QLab.Utility;
using System.Windows;
using System.Windows.Controls;
using QLab.IO.Files;
using QLab.UserControls;
using QLab.Model;
using System.Xml.Serialization;
using System.IO;
using System.ComponentModel.Composition;
using Microsoft.Practices.Prism.ViewModel;
using System.Windows.Input;
using QLab.Controllers.Editor;
using Microsoft.Practices.Prism.Commands;

namespace QLab.Controllers.SolutionExplorer
{
	[Export]
	[PartCreationPolicy(CreationPolicy.Shared)]
	public class SolutionExplorerController : NotificationObject
	{
		protected SolutionItemList _dataSource;
		
		private SolutionExplorerItemBase _selectedItem;
		private TabController _tabController;

		private bool _contextMenuOpened = false;
		private bool _contextMenuVisible = false;
		private bool _addVisible = true;
		private bool _newProjectVisible = true;
		private bool _newFolderVisible = true;
		private bool _newFileVisible = true;
		private bool _removeVisible = true;
		private bool _renameVisible = true;

		private DelegateCommand _newProjectCommand;
		private DelegateCommand _newFolderCommand;
		private DelegateCommand _newFileCommand;
		private DelegateCommand _removeCommand;
		private DelegateCommand _renameCommand;

		/// <summary>
		/// Default constructor
		/// </summary>
		[ImportingConstructor]
		public SolutionExplorerController(TabController TabController)
		{
			_dataSource = new SolutionItemList();
			_tabController = TabController;

			_newProjectCommand = new DelegateCommand(NewProject, CanNewProjectExecute);
			_newFolderCommand = new DelegateCommand(NewFolder, CanNewFolderExecute);
			_newFileCommand = new DelegateCommand(NewFile, CanNewFileExecute);
			_renameCommand = new DelegateCommand(Rename, CanRenameExecute);
			_removeCommand = new DelegateCommand(Remove, CanRemoveExecute);

			#region RoutedEventHandler
			// Register to the SelectedIndex Routed event
			EventManager.RegisterClassHandler(typeof(Control), TreeViewItem.ExpandedEvent,
				(RoutedEventHandler)ItemExpanded);

			// Register to the SelectedIndex Routed event
			EventManager.RegisterClassHandler(typeof(Control), TreeView.SelectedItemChangedEvent,
				(RoutedEventHandler)ItemSelected);

			// Register to the SelectedIndex Routed event
			EventManager.RegisterClassHandler(typeof(Control), TreeView.MouseDoubleClickEvent,
				(RoutedEventHandler)DoubleClick);

			// Register to the ContextMenuOpening Routed event
			EventManager.RegisterClassHandler(typeof(Control), TreeView.ContextMenuOpeningEvent,
				(RoutedEventHandler)ContextMenuOpening);

			// Register to the ContextMenuOpening Routed event
			EventManager.RegisterClassHandler(typeof(Control), TreeView.MouseRightButtonDownEvent,
				(RoutedEventHandler)MouseRightButton);

			#endregion
		}

		#region Properties

		/// <summary>
		/// Gets the list of items to display
		/// </summary>
		public SolutionItemList DataSource
		{
			get { return _dataSource; }
			private set
			{
				_dataSource = value;
				RaisePropertyChanged(() => DataSource);
				RaiseCanExecuteChanged();
			}
		}

		protected SolutionExplorerItemBase SelectedItem
		{
			get { return _selectedItem; }
			set
			{
				if (_selectedItem != value)
				{
					_selectedItem = value;
					RaisePropertyChanged(() => SelectedItem);
					RaiseCanExecuteChanged();
				}
			}
		}

		public ICommand NewProjectCommand { get { return _newProjectCommand; } }
		public ICommand NewFolderCommand { get { return _newFolderCommand; } }
		public ICommand NewFileCommand { get { return _newFileCommand; } }
		public ICommand RemoveCommand { get { return _removeCommand; } }
		public ICommand RenameCommand { get { return _renameCommand; } }

		#region Context Menu 
		
		public bool ContextMenuOpened
		{
			get { return _contextMenuOpened; }
			set
			{
				_contextMenuOpened = value;
				RaisePropertyChanged(() => ContextMenuOpened);
			}
		}

		public bool ContextMenuVisible
		{
			get { return _contextMenuVisible; }
			set
			{
				_contextMenuVisible = value;
				RaisePropertyChanged(() => ContextMenuVisible);
			}
		}

		public bool AddVisible
		{
			get { return _addVisible; }
			set { _addVisible = value; RaisePropertyChanged(() => AddVisible); }
		}
		public bool NewProjectVisible
		{
			get { return _newProjectVisible; }
			set { _newProjectVisible = value; RaisePropertyChanged(() => NewProjectVisible); }
		}
		public bool NewFolderVisible
		{
			get { return _newFolderVisible; }
			set { _newFolderVisible = value; RaisePropertyChanged(() => NewFolderVisible); }
		}
		public bool NewFileVisible
		{
			get { return _newFileVisible; }
			set { _newFileVisible = value; RaisePropertyChanged(() => NewFileVisible); }
		}
		public bool RemoveVisible
		{
			get { return _removeVisible; }
			set { _removeVisible = value; RaisePropertyChanged(() => RemoveVisible); }
		}
		public bool RenameVisible
		{
			get { return _renameVisible; }
			set { _renameVisible = value; RaisePropertyChanged(() => RenameVisible); }
		}
		#endregion

		

		
		#endregion

		#region Solution

		public void CreateSolution(string SolutionPath, string SolutionName, string ProjectName)
		{
			SolutionExplorerItemSolution solution =  new SolutionExplorerItemSolution(SolutionPath, SolutionName, ProjectName);

			_dataSource.Clear();
			_dataSource.Add(solution);
		}

		public void SaveSolution(string SolutionPath)
		{
			SolutionExplorerItemSolution solution =
			  _dataSource.Count.Equals(0) ? null : (SolutionExplorerItemSolution)_dataSource[0];

			if (solution == null)
			{
				// error message
				return;
			}

			solution.Save();
		}

		public void LoadSolution(string SolutionPath)
		{

			SolutionExplorerItemSolution solution;

			XmlSerializer solutionSerializer = new XmlSerializer(typeof(SolutionExplorerItemSolution));
			FileStream solutionFileStream = new FileStream(SolutionPath, FileMode.Open);
			solution = (SolutionExplorerItemSolution)solutionSerializer.Deserialize(solutionFileStream);
			solutionFileStream.Close();

			solution.SolutionRootPath = System.IO.Path.GetDirectoryName(SolutionPath);

			_dataSource.Clear();
			_dataSource.Add(solution);
		}

		#endregion

		#region Contex Menu

		void AddNewItem(object sender, RoutedEventArgs e)
		{

		}
		
		void UpdateContextMenu(SolutionExplorerItemBase item)
		{
			if (item == null)
			{
				ContextMenuOpened = false;
				ContextMenuVisible = false;
				return;
			}

			NewProjectVisible = CanNewProjectExecute();
			NewFolderVisible = CanNewFolderExecute();
			NewFileVisible = CanNewFileExecute();
			RemoveVisible = CanRemoveExecute();
			RenameVisible = CanRenameExecute();

			AddVisible = NewProjectVisible || NewFolderVisible || NewFileVisible;
		}

		#endregion

		#region Event Handlers

		void MenuItemClick(object sender, RoutedEventArgs e)
		{
			/*SolutionExplorerItemBase bi = SelectedSEIB;
			if (bi == null)
				return;

			MenuItem mi = sender as MenuItem;
			if (mi == null)
				return;

			e.Handled = true;

			SolutionExplorerCmItems item_type = (SolutionExplorerCmItems)mi.Tag;
			switch (item_type)
			{
				case SolutionExplorerCmItems.NewProject:
					bi.AddNewItem(SolutionExplorerItemType.Project);
					break;

				case SolutionExplorerCmItems.NewFolder:
					bi.AddNewItem(SolutionExplorerItemType.Folder);
					break;

				case SolutionExplorerCmItems.NewFile:
					bi.AddNewItem(SolutionExplorerItemType.Q_File);
					break;

				case SolutionExplorerCmItems.Rename:

					break;

				case SolutionExplorerCmItems.Remove:
					bi.Parent.ChildItems.Remove(bi);
					break;
			}
			*/
		}

		// event handler for the ContextMenuOpening
		void MouseRightButton(object sender, RoutedEventArgs e)
		{
			TreeViewItem Item = sender as TreeViewItem;
			if (Item != null)
			{
				Item.IsSelected = true;
				e.Handled = true;

				//ContextMenuVisible = true;
			}
			else
			{
				//ContextMenuVisible = false;
			}
		}

		// event handler for the ContextMenuOpening
		void ContextMenuOpening(object sender, RoutedEventArgs e)
		{
			if (e.Source is ContentPresenter)
			{
				TreeViewItem Item = sender as TreeViewItem;
				if (Item != null)
				{
					UpdateContextMenu(Item.Header as SolutionExplorerItemBase);
					//_view.ContextMenu.Visibility = Visibility.Visible;
					ContextMenuVisible = true;
					ContextMenuOpened = true;
				}				
			}
			else if (e.Source is ScrollViewer)
			{
				e.Handled = true;
				ContextMenuVisible = false;
				ContextMenuOpened = false;
			}
		}

		//event handler for the selecting changed
		void ItemSelected(object sender, RoutedEventArgs e)
		{
			TreeView treeView = (TreeView)e.OriginalSource;
			SelectedItem = treeView.SelectedItem as SolutionExplorerItemBase;

			//if (selectedItem != null)
			// MainWindowController.Instance().StatusBar.Text = selectedItem.FullPath;
		}

		//event handler for the Item Expanded event
		void ItemExpanded(object sender, RoutedEventArgs e)
		{
			TreeViewItem itemExpanded = (TreeViewItem)e.OriginalSource;

			/*
			if (itemExpanded != null)
			  MainWindowController.Instance().StatusBar.Text = ((SolutionExplorerItemBase)itemExpanded.Header).Path;
			 */
		}

		//event handler for the Item Double click event
		void DoubleClick(object sender, RoutedEventArgs e)
		{

			TreeViewItem itemExpanded;
			if (e.Source.GetType() != typeof(TreeViewItem))
				return;
			itemExpanded = (TreeViewItem)e.Source;

			if (itemExpanded != null)
			{
				SolutionExplorerItemBase item = (SolutionExplorerItemBase)itemExpanded.Header;
				if (item.Type.Equals(SolutionExplorerItemType.Q_File))
				{
					string path = item.FullPath;
					TextEditorController tec = new TextEditorController(path);
					_tabController.AddTab(tec);

					e.Handled = true;
				}
			}

		}

		#endregion

		#region Methods

		private void RaiseCanExecuteChanged()
		{
			_newProjectCommand.RaiseCanExecuteChanged();
			_newFolderCommand.RaiseCanExecuteChanged();
			_newFileCommand.RaiseCanExecuteChanged();
			_renameCommand.RaiseCanExecuteChanged();
			_removeCommand.RaiseCanExecuteChanged();
		}

		private void NewProject()
		{
			SelectedItem.AddNewItem(SolutionExplorerItemType.Project);
		}
		private bool CanNewProjectExecute()
		{
			if (_dataSource.Count > 0 && SelectedItem != null && SelectedItem.Type == SolutionExplorerItemType.Solution)
				return true;
			else
				return false;
		}

		private void NewFolder()
		{
			SelectedItem.AddNewItem(SolutionExplorerItemType.Folder);
		}
		private bool CanNewFolderExecute()
		{
			if (SelectedItem != null)
			{
				if (SelectedItem.Type == SolutionExplorerItemType.Project || SelectedItem.Type == SolutionExplorerItemType.Folder)
					return true;
			}
			return false;
		}

		private void NewFile()
		{
			SelectedItem.AddNewItem(SolutionExplorerItemType.Q_File);
		}

		private bool CanNewFileExecute()
		{
			if (SelectedItem != null)
			{
				if (SelectedItem.Type == SolutionExplorerItemType.Project || SelectedItem.Type == SolutionExplorerItemType.Folder)
					return true;
			}
			return false;
		}

		private void Remove()
		{
			if (SelectedItem != null)
			{
				SelectedItem.Remove();

				foreach (SolutionExplorerItemBase item in _dataSource)
					item.Save();
			}
		}
		private bool CanRemoveExecute()
		{
			if (SelectedItem != null)
			{
				//Only solution can't be removed
				if (SelectedItem.Type == SolutionExplorerItemType.Solution)
					return false;
				return true;
			}
			return false;
		}

		private void Rename()
		{

		}
		private bool CanRenameExecute()
		{
			return true;
		}

		public Dictionary<string, string> GetSolutionFunctions()
		{
			Dictionary<string, string> functions = new Dictionary<string, string>();
			if (DataSource != null && DataSource.Count > 0)
				TraverseSolutionTree(DataSource[0], functions);
			return functions;
		}

		private void TraverseSolutionTree(SolutionExplorerItemBase node, Dictionary<string, string> functions)
		{
			if (node == null)
				return;

			string text;

			if (node.Type == SolutionExplorerItemType.Q_File)
			{
				text = File.ReadAllText(node.FullPath);
				if (!functions.Keys.Contains(node.NodeText))
					functions.Add(node.NodeText, text);
			}

			if (node.ChildItems != null && node.ChildItems.Count > 0)
			{
				foreach (SolutionExplorerItemBase child in node.ChildItems)
					TraverseSolutionTree(child, functions);
			}
		}

		#endregion
	}
}
